// -----------------------------------------------------------------------
//  <copyright file="DaprAspNetCoreModuleBase.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://www.dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024-05-13 09:05</last-date>
// -----------------------------------------------------------------------

using Dapr.Actors.Runtime;

using DaprPlus.AspNetCore;
using DaprPlus.Builder;
using DaprPlus.Dapr.Events;
using DaprPlus.Dapr.States;
using DaprPlus.Domain.Events;
using DaprPlus.Domain.States;
using DaprPlus.Extensions;

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;


namespace DaprPlus.Dapr;

[ExclusionModules(typeof(AspNetCoreModule))]
public abstract class DaprAspNetCoreModuleBase : AspNetCoreModule
{
    /// <summary>
    /// 将模块服务添加到依赖注入服务容器中
    /// </summary>
    /// <param name="services">依赖注入服务容器</param>
    /// <returns></returns>
    public override IServiceCollection AddServices(IServiceCollection services)
    {
        base.AddServices(services);

        services.Configure<DaprOptions>(DaprOptions.Position);
        services.Configure<DaprAspNetCoreOptions>(AspNetCoreOptions.Position);

        services.AddDaprClient();
        services.AddSingleton<IIntegrationEventBus, DaprIntegrationEventBus>();
        services.Replace<IStateStore, DaprStateStore>(ServiceLifetime.Singleton);

        return services;
    }

    /// <summary>
    /// 应用AspNetCore的服务业务
    /// </summary>
    /// <param name="app">Web应用程序</param>
    public override Task UseModule(WebApplication app)
    {
        var options = app.Services.GetService<IOptions<DaprAspNetCoreOptions>>()?.Value;
        base.UseModule(app);
        if (options?.IsAddDapr == true)
        {
            app.UseCloudEvents();
            app.MapActorsHandlers();
            app.MapSubscribeHandler();
        }

        return Task.CompletedTask;
    }

    protected override void MvcBuilderAction(IServiceCollection services, IMvcBuilder mvcBuilder)
    {
        var options = services.GetOptions<DaprAspNetCoreOptions>(AspNetCoreOptions.Position);
        if (!options.IsAddDapr)
        {
            return;
        }

        mvcBuilder.AddDapr();
        services.AddActors(cfg => { ActorRuntimeAction(services, cfg); });
    }

    protected virtual void ActorRuntimeAction(IServiceCollection services, ActorRuntimeOptions cfg)
    { }
}
